init('CommandService');
(function(){
	var Collections = require('Collections'),
	    StringUtils = require('StringUtils'),
	    session         = require('Session').current;
	
	var List 	= Collections.List,
		Map  	= Collections.Map,
		iterate = Collections.iterate,
		toArray = Collections.toArray,
		gcs     = Collections.gcs,
		filter  = Collections.filter,
		toHTML  = StringUtils.toHTML;
	
	org.jsmud.CommandService = function(){
		this.session = session;
		this.commands= {
			listCommands : {
				onExecute : function(like){
					var results = {values:[], base:like};
					var scope = this;
					this.commandService.getCommands(function(commands){
						for(command in commands){
							if(!like || command.match("^" + like) )
								results.values.push(command);
						}
						results.base = gcs(results.values);
						results.toHTML = function(){
							var html = '';
							var COLUMNS = 4;
							iterate(results.values, function(value, index){
								html += '<div><span>' + value + '</span></div>';
							});
							html = '<span class=commands>' + html + '</span>';
							return html;
						}
						scope.onResponse(results);
					});
				}
			}
		};
		this.reflectiveCommands = {
			$ : function(object){
				this.onExecute = function(){
					//var html  = toHTML(object.data);
					
					this.onResponse(object);
				}
			},
			set : function(object){
				this.onAutoComplete = function(value){
					if( !object ){
						this.onResponse({err:"Failed - No Current Context"});
						return;
					}
					var values = [];
					
					iterate(object.data, function(item, name){ values.push(name); });
					
					if( value )
						values = filter(values, '^' + value);
					var result = {base:gcs(values), values:values};
					result.toHTML = function(){
						return spanWrap(values);
					}
					this.onResponse(result);
				}
				this.onExecute = function(property){
					console.log("onExecute - " + property);
					var value = '';
					if( arguments.length == 2 )
						value = arguments[1];
					else if( arguments.length > 2 ){
						for(var i=1; i < arguments.length; i++)
							value += arguments[i];
					}
					if( value[0] == '/' )
						value = eval('(' + value.substring(1) + ')');
					else
						value = trimQuote(value);
					object.data[property] = value;
					console.log(object);
				}
			}	
		}
	};
	
	org.jsmud.CommandService.prototype = {
		parseCommand : function(cmd){
			var arry = toArray(cmd);
			var name = arry[0];
			var args = [];
			for(var i=1; i<arry.length; i++){
				args[i-1] = arry[i];
			}
			var result = {name:name, args:args};
			return result;
		},
		get : function(commandName, onResponse){
			var scope = this;
			this._get(commandName, function(commandTemplate){
				var command = new org.jsmud.Command(scope, commandName);
				for(field in commandTemplate)
					command[field] = commandTemplate[field];
				onResponse(command);
			});
		},
		_get : function(name, onResponse){
			this.getCommands(function(map){
				onResponse(map[name]);
			});
		},
		_getContextCommands : function(name, value, onResponse){
			if( !value ) return; 
			
			var commandService = this;
			value.getCommands(function(commands){
				var results = {};
				Map.putAll(results, commands);
				Map.putAll(results, commands, function(value, key){ return {key: (name?name+'.':'')+key, value:value} });
				iterate(commandService.reflectiveCommands, function(reflectiveCommand, reflectiveCommandName){
					var command = new reflectiveCommand(value);
					results[name+'.'+reflectiveCommandName] = command;
				});
				onResponse(results);
			});
		},
		getCommands : function(onResponse){
			var results = {};
			Map.putAll(results, this.commands);
			var _chain = require('CommandChain').create();
			var appendMap = function(map){
				Map.putAll(results, map);
				_chain.proceed();
			}
			var finish = function(){
				onResponse(results);
				_chain.proceed();
			}
			_chain
			 .add({method:this._getContextCommands, scope:this, arguments:['room', session.room, appendMap]})
			 .add({method:this._getContextCommands, scope:this, arguments:['user', session.user, appendMap]})
			 .add({method:this._getContextCommands, scope:this, arguments:['item', session.itemService, appendMap]})
			 .add({method:this._getContextCommands, scope:this, arguments:['', session.aliasService, appendMap]})
			 .add({method:finish, scope:this})
			 .execute();
		},
		delegate : function(cmd, args){
			var scope = this;
			return function(){
				scope.doExecute(cmd, args, this.onResponse)
			};
		},
		execute : function(cmd, onResponse){
			var commandAndArgs = this.parseCommand(cmd);
			var scope = this;
			this._get(commandAndArgs.name, function(command){
				if( !command ){
					commandAndArgs.args.splice(0, 0, commandAndArgs.name.substring(1));
					commandAndArgs.name = commandAndArgs.name[0];
					scope._get(commandAndArgs.name, function(command2){
						if(command2){
							scope.doExecute(commandAndArgs.name, commandAndArgs.args, onResponse);
						}else{
							if( onResponse )
								onResponse({err:'Command not found', toHTML:function(){return this.err;}});
						}
					});
				}else{
					scope.doExecute(commandAndArgs.name, commandAndArgs.args, onResponse);
				}
			});
		},
		doExecute : function(commandName, args, onResponse){
			this.get(commandName, function(command){
				command.execute(args, onResponse);
			});
		}
	};
	
	module.exports = new org.jsmud.CommandService();
})()